Skip to content

[Fix] freestyle-mock honors $PORT, drop server.listen string-patch#1432

Open
BilalG1 wants to merge 5 commits into
devfrom
fix/freestyle-mock-port-env
Open

[Fix] freestyle-mock honors $PORT, drop server.listen string-patch#1432
BilalG1 wants to merge 5 commits into
devfrom
fix/freestyle-mock-port-env

Conversation

@BilalG1
Copy link
Copy Markdown
Collaborator

@BilalG1 BilalG1 commented May 14, 2026

Summary

The multi-worker freestyle-mock rewrite (#1430) hardcoded server.listen(8080), which collides with qstash inside the local-emulator container. Supervisord sets PORT=8180 for freestyle-mock specifically to avoid this clash, but the new source ignores process.env.PORT.

The local-emulator Dockerfile previously bridged this with a server.replace('server.listen(8080)', ...) string-patch on the embedded source. The new code is server.listen(8080, () => { ... }) — the literal 'server.listen(8080)' substring no longer matches, so the replace silently no-ops and freestyle-mock binds 8080. qstash then can't start (address already in use: 127.0.0.1:8080 → FATAL), the backend (which depends on qstash) never comes up, and the emulator smoke test times out.

Observed in this run:

smoke-test: FTL address already in use: 127.0.0.1:8080
smoke-test: WARN exited: qstash (exit status 1; not expected)
smoke-test: INFO gave up: qstash entered FATAL state, too many start retries too quickly
[603s] SMOKE TEST FAILED: backend /health?db=1 did not return 200 within 300s

Changes

  • docker/dependencies/freestyle-mock/Dockerfile: server.listen(PORT) where PORT = process.env.PORT || 8080, plus the startup log reflects the actual port.
  • docker/local-emulator/Dockerfile: drop the now-redundant string-replace for the listen call. The two remaining replaces (fs/promises import + node_modules symlink) are unrelated and kept.

Test plan

  • QEMU emulator build workflow passes on this branch (smoke test reaches healthy backend).
  • Verify locally that supervisord's PORT=8180 is honored by freestyle-mock and qstash binds 8080 cleanly.

Summary by CodeRabbit

  • Chores
    • Server listening port is now configurable via PORT (default 8080).
    • Local emulator startup adjusted to better handle dependencies and create a node_modules symlink for smoother local runs.
    • Seed/process transaction timeout increased to 90s for reliability.
    • Local database statement timeout changed to 0 (no statement timeout).
  • CI
    • Added step to enable and validate KVM access during emulator builds.

Review Change Stack

The multi-worker freestyle-mock rewrite (#1430) hardcoded
`server.listen(8080)`, which collides with qstash inside the emulator
container (supervisord sets `PORT=8180` for freestyle-mock). The local-
emulator Dockerfile previously patched this via a string-replace, but
the new source no longer matches the literal pattern, so qstash failed
with `address already in use: 127.0.0.1:8080` and the backend never
came up.

Make the source respect `process.env.PORT` directly and remove the
brittle replace.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-auth-mcp Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-backend Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-dashboard Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-demo Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-docs Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-preview-backend Ready Ready Preview, Comment May 14, 2026 8:41pm
stack-preview-dashboard Ready Ready Preview, Comment May 14, 2026 8:41pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0520860-7a1b-4f22-a3d4-e08c28f31b32

📥 Commits

Reviewing files that changed from the base of the PR and between e2759a1 and 159e29d.

📒 Files selected for processing (1)
  • .github/workflows/qemu-emulator-build.yaml

📝 Walkthrough

Walkthrough

Add a step to the qemu-emulator-build workflow’s test job (amd64) to create a udev rule for /dev/kvm, reload/trigger udev rules, verify /dev/kvm permissions, and log whether KVM is writable or TCG fallback will be used.

Changes

CI KVM enablement

Layer / File(s) Summary
Add KVM udev rule and checks
.github/workflows/qemu-emulator-build.yaml
Inserts a step into the test job (amd64) that creates a udev rule for /dev/kvm, reloads and triggers udev rules, checks /dev/kvm permissions, and logs whether hardware acceleration (KVM) is writable or will fall back to TCG.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • hexclave/stack-auth#1430: Both PRs touch the freestyle-mock generated server/Docker setup; may be related to emulator/test-run integration.

Poem

🐰 Hopped into CI at break of day,
I wrote a rule for KVM to play.
Reloaded udev, gave /dev/kvm a peek,
If hardware's kind, fast tests we'll seek.
If not, TCG hums along the way.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: freestyle-mock now respects the PORT environment variable instead of hardcoding port 8080, and the string-patching workaround is removed.
Description check ✅ Passed The description is comprehensive and well-structured, explaining the root cause (hardcoded port 8080), the context (supervisord sets PORT=8180), the failed string-patch attempt, and the solution clearly.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/freestyle-mock-port-env

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 14, 2026

Greptile Summary

This fix makes the freestyle-mock server honour process.env.PORT (falling back to 8080), resolving a port collision between freestyle-mock and qstash inside the local-emulator container. The companion change removes the now-broken string-patch in the local-emulator Dockerfile that was silently no-oping after the server source changed its listen call signature.

  • freestyle-mock/Dockerfile: Introduces const PORT = process.env.PORT || 8080 so supervisord's PORT=8180 assignment is respected, and updates the startup log to reflect the actual bound port.
  • local-emulator/Dockerfile: Drops the server.replace('server.listen(8080)', ...) string-patch that stopped matching after the listen callback was added; the two unrelated replaces (fs/promises import, node_modules symlink) are preserved.

Confidence Score: 4/5

Safe to merge — directly fixes the port collision that caused the emulator smoke test to fail.

The core fix is correct and targeted: the source now reads process.env.PORT before the listen call, and the dead string-patch is cleanly removed. The only minor gap is that EXPOSE 8080 in the freestyle-mock Dockerfile becomes a documentation mismatch when a non-default port is injected, but this does not affect runtime behaviour.

The EXPOSE directive in docker/dependencies/freestyle-mock/Dockerfile is now slightly misleading since the actual port is environment-driven.

Important Files Changed

Filename Overview
docker/dependencies/freestyle-mock/Dockerfile Replaces hardcoded port 8080 with `process.env.PORT
docker/local-emulator/Dockerfile Removes the now-redundant (and silently no-oping) server.replace('server.listen(8080)', ...) string-patch; the two remaining replaces for fs/promises import and node_modules symlink are unrelated and kept intact.

Sequence Diagram

sequenceDiagram
    participant S as supervisord
    participant FM as freestyle-mock (server.mjs)
    participant QS as qstash

    Note over S: Reads PORT=8180 from supervisord.conf
    S->>FM: "spawn with PORT=8180"
    FM->>FM: "const PORT = process.env.PORT || 8080 → 8180"
    FM->>FM: server.listen(8180)
    Note over FM: Binds :8180 ✓

    S->>QS: spawn (no PORT override)
    QS->>QS: server.listen(8080)
    Note over QS: Binds :8080 ✓ (no collision)
Loading

Comments Outside Diff (1)

  1. docker/dependencies/freestyle-mock/Dockerfile, line 383-390 (link)

    P2 The EXPOSE directive still advertises port 8080, but when PORT=8180 (or any non-default value) is injected by supervisord the container actually listens on a different port. This is a documentation mismatch that can confuse docker inspect, port-mapping documentation, and any tooling that reads EXPOSE to discover the service port.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: docker/dependencies/freestyle-mock/Dockerfile
    Line: 383-390
    
    Comment:
    The `EXPOSE` directive still advertises port 8080, but when `PORT=8180` (or any non-default value) is injected by supervisord the container actually listens on a different port. This is a documentation mismatch that can confuse `docker inspect`, port-mapping documentation, and any tooling that reads `EXPOSE` to discover the service port.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
docker/dependencies/freestyle-mock/Dockerfile:383-390
The `EXPOSE` directive still advertises port 8080, but when `PORT=8180` (or any non-default value) is injected by supervisord the container actually listens on a different port. This is a documentation mismatch that can confuse `docker inspect`, port-mapping documentation, and any tooling that reads `EXPOSE` to discover the service port.

```suggestion
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => {
  console.log(`freestyle-mock listening on :${PORT} (worker pool size ${POOL_SIZE})`);
});
EOF

# ---- network ----------------------------------------------------------------
EXPOSE ${PORT:-8080}
```

Reviews (1): Last reviewed commit: "[Fix] freestyle-mock honors $PORT, drop ..." | Re-trigger Greptile

Under cross-arch arm64 TCG in the qemu-emulator-build CI job, the
deleteMany + createMany batch for ~1500-2000 event rows has been
observed to take 40-50s, exceeding the previously-set 30s Prisma
interactive-transaction ceiling (run 25835455849 hit 44.7s). The
transaction uses deterministic IDs and is idempotent, so a looser
bound has no correctness downside; it only kicks in on the slow TCG
path.
Under cross-arch arm64 TCG in the qemu-emulator-build CI job, a query
in runBulldozerPaymentsInit/paginatedIngress exceeds the 120s
server-side statement_timeout, returning Postgres error 57014
(P2010 from Prisma). KVM/native production runs the same query in
well under a second; the looser bound only kicks in on the slow
emulated path.
The bulldozer payments-seed cascade is O(N^2) in jsonb work because each
setRow propagates through ~65 derived tables and an LFold maintains a
per-customer subscription map that grows without bound. Under cross-arch
arm64 TCG, even handfuls of seed rows blow past any reasonable
statement_timeout — a single OneTimePurchase insert was observed at 304s.

This Postgres instance only runs at qcow2-build time; production has its
own server with its own timeout policy. Setting statement_timeout=0 here
removes the CI flake without touching product behavior.
The smoke-test job has been silently running QEMU under TCG because the
runner's /dev/kvm exists but isn't writable by the default user. The
CLI's accelerator selection is a single check: `[ -w /dev/kvm ]` →
otherwise it falls back to TCG. The build job mirrors this udev rule
already and its KVM-accelerated cold boot completes in ~46s.

Without KVM, recent dev merges have grown the boot's startup work past
the 600s EMULATOR_READY_TIMEOUT under TCG. With KVM, this drops back to
under a minute.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants